package externalSort.Tournament;

import externalSort.filePair;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class runGenerationManagerByTournamentTree {

    private Lock bufferLock;
    private final Semaphore toIdle;
    private final Semaphore toActive;
    private final Semaphore toWriting;
    private final Semaphore toReading;

    // 写入任务
    private final writingTask writer;
    private final readingTask reader;

    // 败者树
    private final tournamentTree loserTree;

    private List<filePair> fileNames;
    private List<bufferSimulator> buffers;

    public runGenerationManagerByTournamentTree(int k, int bufferSize, String inputFileName) throws IOException {
//        System.out.println("=== [runGenerationManager] 初始化开始 ===");
        this.fileNames=new ArrayList<>();

        // 初始化败者树
//        System.out.println("[runGenerationManager] 初始化败者树，k=" + k);
        this.loserTree = new tournamentTree(k);

        // 初始化buffer
//        System.out.println("[runGenerationManager] 初始化3个缓冲区，大小=" + bufferSize);
        List<bufferSimulator> buffers=new ArrayList<>();
        for(int i=0;i<3;i++){
            bufferSimulator cur=new bufferSimulator(bufferSize);
            cur.setState(BufferState.IDLE);
            buffers.add(cur);
//            System.out.println("[runGenerationManager] 创建缓冲区 " + i + "，状态: " + cur.getState());
        }

        this.buffers=buffers;

        BufferedReader br=new BufferedReader(new FileReader(inputFileName));
        this.toIdle=new Semaphore(0);
        this.toActive=new Semaphore(0);
        this.toWriting=new Semaphore(0);
        this.toReading=new Semaphore(3);

//        System.out.println("[runGenerationManager] 信号量初始化: toReading=3, 其他=0");

        this.bufferLock=new ReentrantLock();

        this.writer=new writingTask(buffers,toReading,toWriting,bufferLock,bufferSize,fileNames);
        this.reader=new readingTask(br,bufferLock,toActive,toReading,buffers);
//        System.out.println("=== [runGenerationManager] 初始化完成 ===");
    }


    public List<filePair> startRunningGenerations() throws InterruptedException {
//        System.out.println("=== [runGenerationManager] 开始运行顺串生成 ===");
        Thread readThread=new Thread(this.reader);
        Thread writeThread=new Thread(this.writer);

        readThread.start();
        writeThread.start();
//        System.out.println("[runGenerationManager] 读写线程已启动");

        try{
            // 第一阶段：处理正常数据
//            System.out.println("[runGenerationManager] 进入第一阶段：处理正常数据");
            int cntOfReading=0;
            while(!reader.isAllFinished()||cntOfReading<reader.getCnt()){
//                System.out.println("[tour] readerActive: " + reader.isAllFinished());
//                System.out.println("[tour] 尝试获取toActive, 当前可用: " + toActive.availablePermits());
                toActive.acquire();
                cntOfReading++;
//                System.out.println("[tour] 成功获取toActive");

                bufferLock.lock();
//                System.out.println("[tour] 获取bufferLock");

                bufferSimulator cur=null;
                for(bufferSimulator buffer:buffers){
//                    System.out.println("[tour] 检查缓冲区状态: " + buffer.getState());
                    if(buffer.getState()==BufferState.ACTIVE){
                        cur=buffer;
//                        System.out.println("[tour] 找到ACTIVE缓冲区，大小: " + cur.size());
                        break;
                    }
                }

                if (cur != null) {
                    bufferLock.unlock();
//                    System.out.println("[tour] 释放bufferLock，准备moveOut");

                    moveOut(cur);

                    bufferLock.lock();
//                    System.out.println("[tour] 再次获取bufferLock，设置缓冲区状态为FULL");

                    cur.setState(BufferState.FULL);

//                    System.out.println("[tour] 释放toWriting，当前可用: " + toWriting.availablePermits());
                    toWriting.release();
                    bufferLock.unlock();
//                    System.out.println("[tour] 释放bufferLock");
                }else{
//                    System.out.println("(Error)[tournamentTask]: 未从list中找出ACTIVE的buffer");
                    bufferLock.unlock();
                }

//                System.out.println("[tour] 当前reader.isAllFinished() = " + reader.isAllFinished());
            }

//            System.out.println("[runGenerationManager] 第一阶段完成，进入第二阶段：处理剩余数据");

//            System.out.println("cntOfReading= "+cntOfReading);
//            System.out.println("[runGenerationManager] 第二阶段开始，获取bufferLock");

            // 第二阶段：处理剩余数据

            boolean treeEmpty=false;

            while(!treeEmpty){
//                System.out.println("[runGenerationManager] toReading当前可用: " + toReading.availablePermits());
                toReading.acquire();

                cntOfReading++;

                bufferLock.lock();
//                System.out.println("[runGenerationManager] 获取bufferLock");

                bufferSimulator cur=null;
//                System.out.println("[runGenerationManager] 检查所有缓冲区状态:");
                for(bufferSimulator buffer:buffers){
//                    System.out.println("[runGenerationManager] 缓冲区状态: " + buffer.getState() + "，大小: " + buffer.size());
                    if(buffer.getState()==BufferState.IDLE){
                        cur=buffer;
//                        System.out.println("[runGenerationManager] 找到可用缓冲区: " + buffer.getState());
                        break;
                    }
                }
                bufferLock.unlock();

                if (cur != null) {
                    int out=0;
                    while(out!=Integer.MAX_VALUE&&!cur.isFull()){
                        out= loserTree.moveOut(Integer.MAX_VALUE,true);
                        cur.add(out);
                    }

                    if(out==Integer.MAX_VALUE){
//                        System.out.println("[tour] 讀取到終止符，設置treeEmpty為true");
                        treeEmpty=true;
                    }
//                    System.out.println("[tour] 一個buffer沒有完全汰換掉所有的敗者樹");
                    bufferLock.lock();
                    cur.setState(BufferState.FULL);
                    toWriting.release();
                    bufferLock.unlock();

                }else{
//                    System.out.println("(error)[tour] 沒有IDLE");
                }
            }

//            System.out.println("cntOfReading= "+cntOfReading);
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        readThread.join();
        writeThread.join();
        return this.fileNames;
    }

    private void moveOut(bufferSimulator buffer){
        int n=buffer.size();
        for(int i=0;i<n;i++){
            int cur=buffer.poll();
            int out= loserTree.moveOut(cur, false);
            buffer.add(out);
        }
    }
}